﻿Xrm = window.Xrm || { __namespace: true };
Xrm.UndoAll = Xrm.UndoAll || { __namespace: true };

$(document).ready(function () {
    Xrm.UndoAll.SetDatePickers();
    $("#GetAuditData").kendoButton({
        click: function () {
            Xrm.UndoAll.CreateAuditTable();
        }
    });
});

Xrm.UndoAll.SetDatePickers = function () {
    var d = new Date();
    d.setDate((d.getDate() - 7));
    $("#startDate").kendoDateTimePicker({
        value: d
    });
    $("#startDate").attr("disabled", "disabled");

    $("#endDate").kendoDateTimePicker({
        value: new Date()
    });
    $("#endDate").attr("disabled", "disabled");
};

Xrm.UndoAll.GetAllAuditData = function (page) {
    page = (page == null) ? 1 : page;
    var response = {};
    response.data = {};
    response.data.d = {};
    response.data.d.results = [];
    response.data.d.total = null;

    var request = [];
    request.push("<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">");
    request.push("  <s:Body>");
    request.push("    <RetrieveMultiple xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">");
    request.push("      <query i:type=\"a:QueryExpression\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">");
    request.push("        <a:ColumnSet>");
    request.push("          <a:AllColumns>false</a:AllColumns>");
    request.push("          <a:Columns xmlns:b=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">");
    request.push("            <b:string>action</b:string>");
    request.push("            <b:string>objectid</b:string>");
    request.push("            <b:string>createdon</b:string>");
    request.push("            <b:string>userid</b:string>");
    request.push("            <b:string>auditid</b:string>");
    request.push("          </a:Columns>");
    request.push("        </a:ColumnSet>");
    request.push("        <a:Criteria>");
    request.push("          <a:Conditions>");
    request.push("            <a:ConditionExpression>");
    request.push("              <a:AttributeName>createdon</a:AttributeName>");
    request.push("              <a:Operator>OnOrAfter</a:Operator>");
    request.push("              <a:Values xmlns:b=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">");
    request.push("                <b:anyType i:type=\"c:dateTime\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + new Date($("#startDate").val()).toISOString() + "</b:anyType>");
    request.push("              </a:Values>");
    request.push("              <a:EntityName i:nil=\"true\" />");
    request.push("            </a:ConditionExpression>");
    request.push("            <a:ConditionExpression>");
    request.push("              <a:AttributeName>createdon</a:AttributeName>");
    request.push("              <a:Operator>OnOrBefore</a:Operator>");
    request.push("              <a:Values xmlns:b=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">");
    request.push("                <b:anyType i:type=\"c:dateTime\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + new Date($("#endDate").val()).toISOString() + "</b:anyType>");
    request.push("              </a:Values>");
    request.push("              <a:EntityName i:nil=\"true\" />");
    request.push("            </a:ConditionExpression>");
    request.push("            <a:ConditionExpression>");
    request.push("              <a:AttributeName>operation</a:AttributeName>");
    request.push("              <a:Operator>In</a:Operator>");
    request.push("              <a:Values xmlns:b=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">");
    request.push("                <b:anyType i:type=\"c:int\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">2</b:anyType>");
    request.push("                <b:anyType i:type=\"c:int\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">3</b:anyType>");
    request.push("              </a:Values>");
    request.push("              <a:EntityName i:nil=\"true\" />");
    request.push("            </a:ConditionExpression>");
    request.push("            <a:ConditionExpression>");
    request.push("              <a:AttributeName>action</a:AttributeName>");
    request.push("              <a:Operator>In</a:Operator>");
    request.push("              <a:Values xmlns:b=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">");
    request.push("                <b:anyType i:type=\"c:int\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">2</b:anyType>");
    request.push("                <b:anyType i:type=\"c:int\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">3</b:anyType>");
    request.push("              </a:Values>");
    request.push("              <a:EntityName i:nil=\"true\" />");
    request.push("            </a:ConditionExpression>");
    request.push("          </a:Conditions>");
    request.push("          <a:FilterOperator>And</a:FilterOperator>");
    request.push("          <a:Filters />");
    request.push("        </a:Criteria>");
    request.push("        <a:Distinct>false</a:Distinct>");
    request.push("        <a:EntityName>audit</a:EntityName>");
    request.push("        <a:LinkEntities />");
    request.push("        <a:Orders>");
    request.push("          <a:OrderExpression>");
    request.push("            <a:AttributeName>createdon</a:AttributeName>");
    request.push("            <a:OrderType>Descending</a:OrderType>");
    request.push("          </a:OrderExpression>");
    request.push("        </a:Orders>");
    request.push("        <a:PageInfo>");
    request.push("          <a:Count>10</a:Count>");
    request.push("          <a:PageNumber>" + page + "</a:PageNumber>");
    request.push("          <a:PagingCookie i:nil=\"true\" />");
    request.push("          <a:ReturnTotalRecordCount>true</a:ReturnTotalRecordCount>");
    request.push("        </a:PageInfo>");
    request.push("        <a:NoLock>false</a:NoLock>");
    request.push("      </query>");
    request.push("    </RetrieveMultiple>");
    request.push("  </s:Body>");
    request.push("</s:Envelope>");

    var context = Xrm.UndoShared.GetContext();
    var req = new XMLHttpRequest();
    req.open("POST", encodeURI(context.getClientUrl() + "/XRMServices/2011/Organization.svc/web"), false);
    req.setRequestHeader("Accept", "application/xml, text/xml, */*");
    req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/RetrieveMultiple");
    req.onreadystatechange = function () {
        if (req.readyState === 4) {
            if (req.status === 200) {
                var doc = $.parseXML(req.responseText.replace(/<(\/?)([^:>\s]*:)?([^>]+)>/g, "<$1$3>")); //Remove element namespaces
                var auditHeaders = $(doc).find("Entity");

                for (var i = 0; i < auditHeaders.length; i++) {
                    response.data.d.results.push({
                        "auditid": $(auditHeaders[i]).find("Attributes > KeyValuePairOfstringanyType:contains('auditid') > value").text(),
                        "entity": $(auditHeaders[i]).find("Attributes > KeyValuePairOfstringanyType:contains('objectid') > value > LogicalName").text(),
                        "name": $(auditHeaders[i]).find("Attributes > KeyValuePairOfstringanyType:contains('objectid') > value > Name").text(),
                        "by": $(auditHeaders[i]).find("Attributes > KeyValuePairOfstringanyType:contains('userid') > value > Name").text(),
                        "date": Xrm.UndoShared.FormatDisplayDate(new Date($(auditHeaders[i]).find("Attributes > KeyValuePairOfstringanyType:contains('createdon') > value").text()), "dt"),
                        "action": Xrm.UndoAll.GetActionType($(auditHeaders[i]).find("Attributes > KeyValuePairOfstringanyType:contains('action') > value").text())
                    });
                }

                var total = $(doc).find("TotalRecordCount").text();
                response.data.d.total = total;
            }
        }
    };
    req.send(request.join(""));

    return response;
};

Xrm.UndoAll.CreateAuditTable = function () {
    $("#AuditDetails").kendoGrid({
        dataSource: {
            transport: {
                read: function (options) {
                    var s = Xrm.UndoAll.GetAllAuditData(options.data.page);
                    options.success(s);
                }
            },
            schema: {
                data: "data.d.results",
                total: function (s) {
                    return s.data.d.total;
                }
            },
            pageSize: 10,
            serverPaging: true
        },
        height: 315,
        selectable: 'row',
        change: function (arg) {
            $.map(this.select(), function (item) {
                Xrm.UndoAll.GetSingleAuditDetail($(item).find('td').first().text());
            });
        },
        columns: [
            //{
            //    title: " ",
            //    field: "objectid",
            //    template: function(item) {
            //        if (item.action === "Update") {
            //            return "<a href='#' class='undo' title='Undo'></a>";
            //        } else {
            //            return "<a href='#' class='undo' title='Restore'></a>";
            //        }
            //    },
            //    encoded: false,
            //    width: 35
            //},
            {
                field: "auditid",
                hidden: true
            }, {
                field: "name",
                title: "Name"
            }, {
                field: "entity",
                title: "Type"
            }, {
                field: "action",
                title: "Action"
            }, {
                field: "by",
                title: "By"
            }, {
                field: "date",
                title: "Date"
            }
        ],
        pageable: {
            buttonCount: 3
        }
    });
};


Xrm.UndoAll.GetActionType = function (action) {
    switch (action) {
        case "2":
            return "Update";
        case "3":
            return "Delete";
        default:
            return "Unknown";
    }
};

Xrm.UndoAll.GetSingleAuditDetail = function (auditId) {
    var request = [];
    var response = {};
    response.data = {};
    response.data.d = {};
    response.data.d.results = [];
    response.data.d.total = null;

    request.push("<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">\n");
    request.push("  <s:Body>\n");
    request.push("    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">\n");
    request.push("      <request i:type=\"b:RetrieveAuditDetailsRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">\n");
    request.push("        <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">\n");
    request.push("          <a:KeyValuePairOfstringanyType>\n");
    request.push("            <c:key>AuditId</c:key>\n");
    request.push("            <c:value i:type=\"d:guid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/\">" + auditId + "</c:value>\n");
    request.push("          </a:KeyValuePairOfstringanyType>\n");
    request.push("        </a:Parameters>\n");
    request.push("        <a:RequestId i:nil=\"true\" />\n");
    request.push("        <a:RequestName>RetrieveAuditDetails</a:RequestName>\n");
    request.push("      </request>\n");
    request.push("    </Execute>\n");
    request.push("  </s:Body>\n");
    request.push("</s:Envelope>\n");

    var context = Xrm.UndoShared.GetContext();
    var req = new XMLHttpRequest();
    req.open("POST", encodeURI(context.getClientUrl() + "/XRMServices/2011/Organization.svc/web"), false);
    req.setRequestHeader("Accept", "application/xml, text/xml, */*");
    req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
    req.onreadystatechange = function () {
        if (req.readyState === 4) {
            if (req.status === 200) {
                var doc = $.parseXML(req.responseText.replace(/<(\/?)([^:>\s]*:)?([^>]+)>/g, "<$1$3>")); //Remove element namespaces
                var auditHeader = $(doc).find("KeyValuePairOfstringanyType:first");
                var id = $(auditHeader[0]).find("Attributes > KeyValuePairOfstringanyType:contains('objectid') > value > Id").text();
                var entity = $(auditHeader[0]).find("Attributes > KeyValuePairOfstringanyType:contains('objectid') > value > LogicalName").text();

                Xrm.UndoAll.ParseAndDisplay(auditHeader, id, entity);
            }
        }
    };
    req.send(request.join(""));
};

Xrm.UndoAll.ParseAndDisplay = function (auditDetails, id, entity) {
    Xrm.UndoShared.AuditDetail = Xrm.UndoShared.ObjectifyResults(auditDetails);
    if (Xrm.UndoAll.IsAuditDetailPresent()) {
        Xrm.UndoShared.GetMetadata(Xrm.UndoShared.AuditDetail, id, entity, function (auditDetail) {
            Xrm.UndoShared.AuditDetail = auditDetail;
            if (Xrm.UndoAll.IsAuditDetailPresent()) {
                Xrm.UndoShared.DisplayAuditDetail(Xrm.UndoShared.AuditDetail, id, Xrm.UndoAll.Revert_Callback);
            } else {
                Xrm.UndoShared.DisplayNoDataMessage("#AuditDetail", "No data to display or auditing is not enabled");
            }
        });
    } else {
        Xrm.UndoShared.DisplayNoDataMessage("#AuditDetail", "No data to display or auditing is not enabled");
    }
};

//Verifies the existing of valid audit data to be displayed
Xrm.UndoAll.IsAuditDetailPresent = function () {
    if (Xrm.UndoShared.AuditDetail.length === 0) return false;
    for (var i = 0; i < Xrm.UndoShared.AuditDetail.length; i++) {
        if (Xrm.UndoShared.AuditDetail[i].changes.length > 0) return true;
    }
    return false;
};

Xrm.UndoAll.Revert_Callback = function () {
    setTimeout(function () { //Timeout to handle the re-query of audit data not being current
        Xrm.UndoShared.AuditDetail = [];
        $("#AuditDetail").html("").removeClass("k-grid k-widget").attr("data-role", null);
        Xrm.UndoAll.CreateAuditTable();
    }, 1000);
};